from point import Point, UnitCirclePoint
from line import Line
from arrangement import Arrangement, LinkedPoint
from segments import Segments
import math

#holds the data for one problem (a room and a robot),
#contains the solve function.
class Problem(object):
    def __init__(self, room, robot):
        self._room = room
        self._robot = robot
        self._is_solved = False
        self._solution = None
    @property
    def robot(self):
        return self._robot
    @property
    def room(self):
        return self._room
    @property
    def is_solved(self):
        return self._is_solved
    def get_solution(self):
        if (not self._is_solved):
            self.solve()
        return self._solution
    def solve(self):
        circle = Arrangement.combine(self.room.arrangeOnUnitCircle(), self.robot.arrangeOnUnitCircle())

        def findNext(current, arr):
            while current.original.arrangement != arr:
                current = current.next
            return current
        def findPrev(current, arr):
            while current.original.arrangement != arr:
                current = current.previous
            return current
        def getFurthestBetween(first, last):
            mean = (first.angle + last.angle) / 2
            best = None
            while (first != last) or (first.original.arrangement != last.original.arrangement):
                if ((first.original.arrangement == self.robot) and ((not best) or (abs(best.angle - mean) > abs(first.angle - mean)))):
                    best = first
                first = first.next
            return best
        def getNearests(room1, room2):
            robot1 = findPrev(room1, self.robot)
            robot2 = findNext(room2, self.robot)
            if (abs(robot1.angle - room1.angle) < abs(robot2.angle - room2.angle)):
                return robot1
            return robot2
        segments = Segments()
        room1 = None
        room2 = findNext(circle[0], self.room)
        while len(segments) < len(self.room):
            room1 = room2
            room2 = findNext(room1.next, self.room)
            best = getFurthestBetween(room1, room2)
            if (not best):
                best = getNearests(room1, room2)

            if (room1.original.original.x == room2.original.original.x):
                l = Line.new_x_line(room1.original.original.x - best.original.original.x)
            else:
                l_old = Line(room1.original.original, room2.original.original)
                movement = best.original.original.y - l_old.m * best.original.original.x
                l = Line.new_line(l_old.m, l_old.b - movement)
            segments.add(l)
        self._solution = segments.intersections
        self._is_solved = True
